package com.distribute.framework.dao.impl;


import com.distribute.framework.core.web.helper.Utils;
import com.distribute.framework.core.web.util.Page;
import com.distribute.framework.core.util.Function;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Repository;
import javax.annotation.Resource;

import org.mybatis.spring.SqlSessionTemplate;

import com.distribute.framework.plugin.*;
import com.distribute.framework.dao.ISrvEventHeedDao;
import com.distribute.framework.model.SrvEventHeed;
import com.distribute.framework.model.DefineException;


/**
 * 事件关注的Dao实现
 * @author 飞啊飘啊
 * 感谢ibatis的持久层框架 
 */
@SuppressWarnings("unchecked")
@Repository(value="srvEventHeedDao")
public class SrvEventHeedDao implements ISrvEventHeedDao
{
	@Resource
    private SqlSessionTemplate distributeSysSqlSessionTemplate;
	/************LAZY3Q_DEFINE_CODE************/
	/************LAZY3Q_DEFINE_CODE************/
	
	/**
	 * 自定义加工处理params,可以添加表别名、联表查询等操作
	 * 可在此动态设置数据源，以达到分库分表的目的
	 * @param params
	 * @return
	 */
	private Map custom(Map params){
		/************LAZY3Q_DAO_CUSTOM************/
		/************LAZY3Q_DAO_CUSTOM************/
		return params;
	}
	
	/**
	 * 自定义加工处理params,可以添加表别名、联表查询等操作
	 * 可在此动态设置数据源，以达到分库分表的目的
	 * @param params
	 * @return
	 */
	private SrvEventHeed custom(SrvEventHeed params){
		/************LAZY3Q_CUSTOM_MODEL************/
		/************LAZY3Q_CUSTOM_MODEL************/
		return params;
	}
	/************LAZY3Q_DEFINE_FUNCTION************/
	/************LAZY3Q_DEFINE_FUNCTION************/
	
	/**
	 * 为某些需要加like的key加%
	 * @param params
	 * @return
	 */
	private Map filter(Map params){
		//为模糊匹配的varchar类型字段加上%号
		String[] likes={
			"sehHeedType"			
		};
		for(String key:likes){
			String value=(String) params.get(key);
			if(value==null || value.trim().equals(""))
				params.remove(key);
			else
				params.put(key, "%"+value.replaceAll("%", "")+"%");
		}
		
		//如果输入的字串大于设定的长度，并且包含半角逗号的，使用in方法进行查询
		String[] ins={
			"sehId"			
		};
		for(String key:ins){
			String value=(""+params.get(key)).replace("%", "");
			if(value.indexOf(",")>-1 && value.startsWith("[") && value.endsWith("]")){
				params.put(key+"In", value.replace("'","''").replace(",", "','").replace("[", "'").replace("]", "'"));
			}
		}
		
		Object[] keys = {};
		keys = params.keySet().toArray(keys);
		for(Object key:keys){
			if(key.toString().endsWith("Not"))continue;
			Object value=params.get(key);
			if(value==null || value.toString().trim().equals(""))
				params.remove(key);
		}
		
		return params;
	}
	

	/**
	 * 获取所有事件关注
	 * @return
	 */	
	public List<SrvEventHeed> getSrvEventHeedList(Map params,Integer offset,Integer size)
	{		
		params = custom(params);
		params.put("SIZE", size);//放入查询条数，作为缓存唯一依据
		String json = params.toString();
		String md5 = Utils.md5(json);
		
		List<SrvEventHeed> list = new ArrayList();
		Boolean bInReject = false;
		//如果查询参数中有下列字段中任意之一，则不作缓存
		for(String reject:new String[]{"In-Reject","sehUpdateTime","sehUpdateTimeStart","sehUpdateTimeEnd","sehAddTime","sehAddTimeStart","sehAddTimeEnd"}){
			if(params.get(reject)!=null){
				bInReject = true;
				break;
			}
		}
		//如果有连接查询，则不作缓存
		for(String reject:new String[]{"In-Reject","SehEventType","SehHeedUser"}){
			if(params.get(reject)!=null){
				bInReject = true;
				break;
			}
		}
		if(!bInReject){
			String sParam = Cache.getValue(SrvEventHeed.M.class, md5);					
			List caches = (List)Cache.getObject(SrvEventHeed.M.class, md5);
			if(caches!=null){
				if(Utils.equals(sParam, json)){
					for(Object item:caches){
						SrvEventHeed cacheObject = (SrvEventHeed) Cache.getObject(SrvEventHeed.class, Long.parseLong(""+item));
						if(cacheObject==null){//如果缓存对象为空，表示对象有修改过，则放弃当前列表缓存
							list = new ArrayList();
							Cache.deleteObject(SrvEventHeed.M.class, md5);
							Cache.deleteValue(SrvEventHeed.M.class, md5);
							break;
						}else{
							list.add(cacheObject);
						}
					}
					return list;
				}else{
					Utils.trace("缓存冲突",sParam,json);
					Cache.deleteObject(SrvEventHeed.M.class, md5);
					Cache.deleteValue(SrvEventHeed.M.class, md5);
				}
			}
		}
		
		if(size!=null && size!=-1)
			params.put("limit", size);
		if(offset!=null && params.get("limit")!=null)
			params.put("offset",offset);
		
	
		list = distributeSysSqlSessionTemplate.selectList("getSrvEventHeedList", params);
		if(size<1024){
			List caches = new ArrayList();
			for(SrvEventHeed srvEventHeed:list){
				if(!bInReject){
					caches.add(srvEventHeed.getSehId());
				}
				Cache.setObject(SrvEventHeed.class,srvEventHeed.getSehId(), srvEventHeed);
			}
			if(!bInReject){
				Cache.setObject(SrvEventHeed.M.class, md5, caches, Cache.defaultSeconds());
				Cache.setValue(SrvEventHeed.M.class, md5, json, Cache.defaultSeconds());
			}
		}		
		
		return list;
	}
	
	
	/**
	 * 获取事件关注统计
	 * @return
	 */
	public List getSrvEventHeedStats(Map params,Map<String,Object> groups,Map<String,Object> sums)
	{
		params = custom(params);
		params=filter(params);
		
		String groupSql="";
		for(Map.Entry<String, Object> item : groups.entrySet())
			if(!Utils.empty(item.getKey()))
				groupSql+=(groupSql.equals("")?"":",")+item.getValue().toString().replace("{key}",item.getKey());
		if(groups.get("definex")!=null)
			groupSql+=(groupSql.equals("")?"":",")+groups.get("definex");
		if(!groupSql.equals(""))
			groupSql = "group by "+groupSql;
		if(params.get("desc")!=null)
			groupSql+=" order by {key} desc ".replace("{key}",params.get("desc").toString());
		else if(params.get("asc")!=null)
			groupSql+=" order by {key} asc ".replace("{key}",params.get("asc").toString());
		if(!groupSql.equals(""))
			groupSql+=" limit 512 ";
			
		String selectSql="count(*) as 'count'";
		for(Map.Entry<String, Object> item : sums.entrySet())
			if(!Utils.empty(item.getKey()))
				selectSql+=(selectSql.equals("")?"":",")+item.getValue().toString().replace("{key}",item.getKey())+(item.getValue().toString().indexOf(" as ")==-1 ? (" as "+item.getKey()) : "");
		for(Map.Entry<String, Object> item : groups.entrySet())
			if(!Utils.empty(item.getKey()))
				selectSql+=(selectSql.equals("")?"":",")+item.getKey()+" as '"+item.getKey()+"'";
		if(sums.get("definex")!=null)
			selectSql+=(selectSql.equals("")?"":",")+sums.get("definex");
		
		params.put("select",selectSql);
		params.put("group",groupSql);
		return distributeSysSqlSessionTemplate.selectList("getSrvEventHeedStats", params);
	}

	/**
	 * 获取事件关注分页
	 * @return
	 */
	public Page getSrvEventHeedPage(int page,int size,Map params)
	{
		params = custom(params);
		params=filter(params);
		
		if(size<1)size=20;
		
		//获取分页总数
		Long count= (Long) distributeSysSqlSessionTemplate.selectOne("getSrvEventHeedCount", params);
		//取分页的队列
		
		params.put("limit", size);
		params.put("offset", (int)Page.test(page,size,count));
		List list=distributeSysSqlSessionTemplate.selectList("getSrvEventHeedPage", params);
		//返回一个包装分页对象
		return new Page(page,size,count,list);
	}
	
	/**
	 * 获取事件关注数量
	 * @return
	 */	
	public Long getSrvEventHeedCount(Map params)
	{
		params = custom(params);
		params=filter(params);
		return (Long) distributeSysSqlSessionTemplate.selectOne("getSrvEventHeedCount", params);
	}
	
	/**
	 * 获取事件关注自定义求和表达式,比如求ID平均值:eval="avg(id)"
	 * @return
	 */	
	public <T> T getSrvEventHeedEval(String eval,Map params)
	{
		params = custom(params);
		params=filter(params); 
		params.put("eval",eval);
		Map result = (Map) distributeSysSqlSessionTemplate.selectOne("getSrvEventHeedEval", params);
		return result==null?null:(T)result.get("eval");
	}
	
	
	/**
	 * 根据查询条件取单个事件关注
	 * @param params
	 * @return
	 */
	public SrvEventHeed getSrvEventHeed(Map params)
	{		
		params = custom(params);
		String md5 = null;
			
		List<SrvEventHeed> list=this.getSrvEventHeedList(params,0,1);
		SrvEventHeed srvEventHeed = list.isEmpty()?null:list.get(0);
		if(srvEventHeed!=null)
			Cache.setValue(SrvEventHeed.class,srvEventHeed.getId(), srvEventHeed.getKeyValue());
		if(srvEventHeed!=null){
			Cache.setObject(SrvEventHeed.class,srvEventHeed.getId(), srvEventHeed);
		}else if(md5!=null){
			Cache.setObject(SrvEventHeed.F.class, md5, -1l);
		}
		
		return srvEventHeed;
	}
		
	/**
	 * 根据ID取事件关注
	 * @param id
	 * @return
	 */
	public SrvEventHeed getSrvEventHeedById(Long id)
	{
		if(id==null)
			return null;
	
		SrvEventHeed srvEventHeed = (SrvEventHeed) Cache.getObject(SrvEventHeed.class, id);
		if(srvEventHeed!=null)
			return srvEventHeed;
		if(srvEventHeed!=null && srvEventHeed.getSehId()==null)
			return null;
			
		Map params=new HashMap();
		params.put("id", id);
		params = custom(params);
		srvEventHeed = (SrvEventHeed) distributeSysSqlSessionTemplate.selectOne("getSrvEventHeedById",params);
		if(srvEventHeed!=null)
			Cache.setValue(SrvEventHeed.class,id, srvEventHeed.getKeyValue());
		else
			Cache.setValue(SrvEventHeed.class,id, "　" );
		if(srvEventHeed!=null){
			Cache.setObject(SrvEventHeed.class,id, srvEventHeed);
		}
		return srvEventHeed;
	}
	
	/**
	 * 根据ID取事件关注(不缓存)
	 * @param id
	 * @return
	 */
	public SrvEventHeed GetSrvEventHeedById(Long id){
		Map params=new HashMap();
		params.put("id", id);
		params = custom(params);
		return  (SrvEventHeed) distributeSysSqlSessionTemplate.selectOne("getSrvEventHeedById",params);
	}
	

	/**
	 * 保存事件关注
	 * @param srvEventHeed
	 */
	public SrvEventHeed saveSrvEventHeed(SrvEventHeed srvEventHeed)
	{
		srvEventHeed = custom(srvEventHeed);
		Trigger.on(SrvEventHeed.class,Trigger.BEFOR,Trigger.SAVE,srvEventHeed);
		distributeSysSqlSessionTemplate.insert("saveSrvEventHeed", srvEventHeed);
		Long id=srvEventHeed.getSehId();
		Cache.setValue(SrvEventHeed.class,id, srvEventHeed.getKeyValue());
		Cache.setObject(SrvEventHeed.class,id,srvEventHeed);
		Cache.clearObject(SrvEventHeed.M.class);
		Cache.clearValue(SrvEventHeed.M.class);
		return Trigger.on(SrvEventHeed.class,Trigger.AFTER,Trigger.SAVE,srvEventHeed);
	}

	

	/**
	 * 更新事件关注
	 * @param srvEventHeed
	 */
	public int updateSrvEventHeed(SrvEventHeed srvEventHeed)
	{
		srvEventHeed = custom(srvEventHeed);
		SrvEventHeed dbSrvEventHeed = SrvEventHeed.get(srvEventHeed.getId());
		Trigger.on(SrvEventHeed.class,Trigger.BEFOR,Trigger.UPDATE,srvEventHeed);
		int rows = distributeSysSqlSessionTemplate.update("updateSrvEventHeed", srvEventHeed);
		//srvEventHeed = this.GetSrvEventHeedById(srvEventHeed.getSehId());
		if(srvEventHeed!=null){
			Cache.setValue(SrvEventHeed.class,srvEventHeed.getSehId(), srvEventHeed.getKeyValue());
			Cache.setObject(SrvEventHeed.class,srvEventHeed.getSehId(),srvEventHeed);
		}
		Cache.clearObject(SrvEventHeed.M.class);
		Cache.clearValue(SrvEventHeed.M.class);
		Trigger.on(SrvEventHeed.class,Trigger.AFTER,Trigger.UPDATE,srvEventHeed);
		Trigger.on(SrvEventHeed.class,dbSrvEventHeed,srvEventHeed);
		return rows;
	}
	/**
	 * 更新事件关注非空字段
	 * @param srvEventHeed
	 */
	public int updateSrvEventHeed$NotNull(SrvEventHeed srvEventHeed)
	{
		srvEventHeed = custom(srvEventHeed);
		SrvEventHeed dbSrvEventHeed = SrvEventHeed.get(srvEventHeed.getId());
		SrvEventHeed updated = srvEventHeed;
		Trigger.on(SrvEventHeed.class,Trigger.BEFOR,Trigger.UPDATE_NOTNULL,updated);
		int rows = distributeSysSqlSessionTemplate.update("updateSrvEventHeed$NotNull", srvEventHeed);
		srvEventHeed = this.GetSrvEventHeedById(srvEventHeed.getSehId());
		if(srvEventHeed!=null){
			Cache.setValue(SrvEventHeed.class,srvEventHeed.getSehId(), srvEventHeed.getKeyValue());
			Cache.setObject(SrvEventHeed.class,srvEventHeed.getSehId(),srvEventHeed);
		}
		Cache.clearObject(SrvEventHeed.M.class);
		Cache.clearValue(SrvEventHeed.M.class);
		updated.setValues("$NotNull", true);
		Trigger.on(SrvEventHeed.class,Trigger.AFTER,Trigger.UPDATE_NOTNULL,updated);
		Trigger.on(SrvEventHeed.class,dbSrvEventHeed,srvEventHeed);
		return rows;
	}
	
	
	
	/**
	 * 根据条件更新事件关注
	 * @param values
	 * @param params
	 */
	public int updateSrvEventHeedByConfirm(Map values, Map params){
	
		params = custom(params);
		
		for(Map.Entry<String,Object> entry:((Map<String,Object>)values).entrySet())
			params.put("V_"+entry.getKey(), entry.getValue());
		Long count = this.getSrvEventHeedCount(params);
		Trigger.on(SrvEventHeed.class,Trigger.BEFOR,Trigger.UPDATE_BY,params);
		List<SrvEventHeed> updates = new ArrayList();
		if(count<32 && Trigger.have(SrvEventHeed.class,params)){
			updates = getSrvEventHeedList(params,0,32);
		}
		//如果更新条数大于255，则清空缓存
		if(count>255){
			if(!Utils.equals(""+params.get("batchUpdatePassword"), "true")){
				throw new DefineException("一次更新超过255,但未输入密码");
			}
			Cache.clearValue(SrvEventHeed.class);
			Cache.clearObject(SrvEventHeed.class);
		}else{
			params.put("eval","seh_id");
			List<Map> result = distributeSysSqlSessionTemplate.selectList("getSrvEventHeedEval", params);
			for(Map map:result){
				Cache.deleteValue(SrvEventHeed.class, map.get("eval"));
				Cache.deleteObject(SrvEventHeed.class, map.get("eval"));
			}
		}
		Cache.clearObject(SrvEventHeed.M.class);
		Cache.clearValue(SrvEventHeed.M.class);
			
		int rows = distributeSysSqlSessionTemplate.update("updateSrvEventHeedBy", params);
		if(rows==1){
			Trigger.on(SrvEventHeed.class,Trigger.AFTER,Trigger.UPDATE,getSrvEventHeed(params));
		}else{
			Trigger.on(SrvEventHeed.class,Trigger.AFTER,Trigger.UPDATE_BY,params);
		}
		if(count<32 && rows>0 && updates.size()>0){
			Map<Long,SrvEventHeed> mapping = new HashMap();
			String ids = "";
			for(SrvEventHeed srvEventHeed:updates){
				mapping.put(srvEventHeed.getId(), srvEventHeed);
				ids+=(ids.equals("")?"":",")+srvEventHeed.getId();
			}
			updates = SrvEventHeed.where.sehIdIn(ids).list(32);
			for(SrvEventHeed srvEventHeed:updates){
				Trigger.on(SrvEventHeed.class,mapping.get(srvEventHeed.getId()),srvEventHeed);
			}
		}
		
		return rows;
	}
	
	

	/**
	 * 根据ID删除一个事件关注
	 * @param id
	 */
	public void deleteSrvEventHeedById(Long id)
	{
		Map params=new HashMap();
		params.put("sehId", id);
		params.put("id", id);
		params = custom(params);
		Trigger.on(SrvEventHeed.class,Trigger.BEFOR,Trigger.DELETE,params);
		distributeSysSqlSessionTemplate.delete("deleteSrvEventHeedById", params);
		Cache.deleteValue(SrvEventHeed.class, id);
		Cache.deleteObject(SrvEventHeed.class, id);
		Cache.clearObject(SrvEventHeed.M.class);
		Cache.clearValue(SrvEventHeed.M.class);
		Trigger.on(SrvEventHeed.class,Trigger.AFTER,Trigger.DELETE,params);
	}
	/**
	 * 根据ID逻辑删除事件关注 
	 * @param id
	 * @return
	 */
	public void removeSrvEventHeedById(Long id)
	{
		Map params=new HashMap();
		params.put("sehId", id);
		params.put("id", id);
		params = custom(params);
		Trigger.on(SrvEventHeed.class,Trigger.BEFOR,Trigger.DELETE,params);
		distributeSysSqlSessionTemplate.update("removeSrvEventHeedById", params);
		Cache.deleteValue(SrvEventHeed.class, id);
		Cache.deleteObject(SrvEventHeed.class, id);
		Cache.clearObject(SrvEventHeed.M.class);
		Cache.clearValue(SrvEventHeed.M.class);
		Trigger.on(SrvEventHeed.class,Trigger.AFTER,Trigger.DELETE,params);
	}
	
	/**
	 * 根据条件删除事件关注
	 * @param params
	 */
	public void deleteSrvEventHeedByConfirm(Map params){
	
		params = custom(params);
		
		Trigger.on(SrvEventHeed.class,Trigger.BEFOR,Trigger.DELETE_BY,params);
		//如果更新条数大于255，则清空缓存
		if(this.getSrvEventHeedCount(params)>255){
			if(!Utils.equals(""+params.get("batchDeletePassword"), "true")){ 
				throw new DefineException("一次删除超过255,但未输入密码");
			}
			Cache.clearValue(SrvEventHeed.class);
			Cache.clearObject(SrvEventHeed.class);
		}else{
			params.put("eval","seh_id");
			List<Map> result = distributeSysSqlSessionTemplate.selectList("getSrvEventHeedEval", params);
			for(Map map:result){
				Cache.deleteValue(SrvEventHeed.class, map.get("eval"));
				Cache.deleteObject(SrvEventHeed.class, map.get("eval"));
			}
		}
		Cache.clearObject(SrvEventHeed.M.class);
		Cache.clearValue(SrvEventHeed.M.class);
		
		int rows = distributeSysSqlSessionTemplate.update("deleteSrvEventHeedBy", params);
		
		Trigger.on(SrvEventHeed.class,Trigger.AFTER,Trigger.DELETE_BY,params);
	}
	
	
	/**
	 * 事务处理
	 */
	public <T> T executeTransaction(Function function) {
		return function.execute();	
	}

}